package com.lancoo.cvas.arrangecourse.dataprocess;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.lancoo.cvas.arrangecourse.common.BinaryUtil;
import com.lancoo.cvas.arrangecourse.entities.TeachingClassUnit;
import com.lancoo.cvas.arrangecourse.entities.TimeslotRoom;
import com.lancoo.cvas.pojo.dto.ArrangeTeachingClassDto;
import com.lancoo.cvas.pojo.dto.ArrangeTeachingClassRuleDto;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 生成排课教学班单元数据
 * @Author Fortysun
 * @Date 2023/5/16 17:50
 **/
@Slf4j
public class GenerateSchedulingData {

    /**
     * 将拆班课程生成的教学班，转换成教学班排课单元
     * 拆班的教学班，连上节次都是1，只需要按照周学时，拆成周学时数量的排课单元即可
     * 比如：周学时是3，那只需要拆成3个排课单元即可
     *
     * @param taskId            排课计划id
     * @param teachingClassList 需要转换的教学班列表信息
     * @param startPos          教学班排课单元生成的起始位置
     * @return
     */
    public LinkedList<TeachingClassUnit> convertToSplitTeachingClassUnit(Integer taskId,
                                                                         List<ArrangeTeachingClassDto> teachingClassList,
                                                                         Integer startPos) {
        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            //用于存放排课单元数据
            LinkedList<TeachingClassUnit> teachingclassUnitList = new LinkedList<>();
            int teachingClassUnitIndex = startPos;
            for (ArrangeTeachingClassDto teachingClass : teachingClassList) {
                //获取教学班的某个授课类型的周学时数量
                Integer weekNum = teachingClass.getWeekNum();
                //过滤掉脏数据，有些教学班没有设置周学时的话，直接跳过
                if (weekNum != null) {
                    //连上次数为0，默认就按照连上节次是1节，去拆分生成教学班排课单元
                    teachingClassUnitIndex = connectNumberIsZero(teachingClass, weekNum,
                            taskId, teachingClassUnitIndex, teachingclassUnitList,new ArrayList<>());
                }
            }

            return teachingclassUnitList;
        }
        log.info("GenerateSchedulingData--convertToSplitTeachingClassUnit: 没有需要转换成教学班单元的教学班信息~！！");
        //不需要排课，返回空
        return null;
    }

    /**
     * 连上次数为0，默认就按照连上节次是1节，去拆分生成教学班排课单元
     *
     * @param teachingClass          教学班对象
     * @param weekNum                周学时
     * @param taskId                 计划id
     * @param teachingClassUnitIndex 生成的教学班排课单元id
     * @param teachingclassUnitList  用来存储的教学班排课单元列表信息
     * @return
     */
    private int connectNumberIsZero(ArrangeTeachingClassDto teachingClass,
                                    Integer weekNum,
                                    Integer taskId,
                                    int teachingClassUnitIndex,
                                    LinkedList<TeachingClassUnit> teachingclassUnitList,
                                    List<ArrangeTeachingClassRuleDto> courseFixList) {
        //排除课程里面重复的
        List<String> tcFix = teachingClass.getFixTimeslotCodes();
        if (CollUtil.isNotEmpty(tcFix)){
            List<String> course = courseFixList.stream().map(ArrangeTeachingClassRuleDto::getTimeCode).collect(Collectors.toList());
            tcFix = tcFix.stream().filter(o -> !course.contains(o)).collect(Collectors.toList());
            teachingClass.setFixTimeslotCodes(tcFix);
        }

        //获取固排的课时
        List<String> fixTimeslotCodes = teachingClass.getFixTimeslotCodes();

        //通过周学时数量，生成指定数量的教学班排课单元
        for (int i = 0; i < weekNum; i++) {
            //计算教学班排课单元的id
            teachingClassUnitIndex++;
            //生成排课教学班
            TeachingClassUnit teachingClassUnit = generateTeachingClassUnit(teachingClass,
                    teachingClassUnitIndex,
                    taskId,
                    teachingClass.getWeek());
            //将教学班的连上节次设为1
            teachingClassUnit.setConnectSection(1);
            //将教学班的连上次数设为0
            teachingClassUnit.setConnectNumber(0);


            //设置固排课时
            String fixTimeCode = null;
            //从课程那边拿
            if (CollUtil.isNotEmpty(courseFixList)){
                fixTimeCode = courseFixList.get(0).getTimeCode();
                courseFixList.remove(0);
            }

            if (StrUtil.isEmpty(fixTimeCode)){
                if (CollUtil.isNotEmpty(fixTimeslotCodes)) {
                    fixTimeCode = fixTimeslotCodes.get(0);
                    fixTimeslotCodes.remove(0);
                }
            }

            if (StrUtil.isNotEmpty(fixTimeCode)){
                teachingClassUnit.setFixTimeslotCodes(Collections.singletonList(fixTimeCode));
            }else {
                teachingClassUnit.setFixTimeslotCodes(new ArrayList<>());
            }
            //将生成的排课教学班，添加到返回的列表中
            teachingclassUnitList.add(teachingClassUnit);
        }
        return teachingClassUnitIndex;
    }

    /**
     * 生成排课教学班单元
     *
     * @param taskId            排课计划id
     * @param teachingClassList 需要转换的教学班列表信息
     * @param startPos          教学班排课单元生成的起始位置
     * @return
     */
    public LinkedList<TeachingClassUnit> convertToTeachingClassUnit(Integer taskId,
                                                                    List<ArrangeTeachingClassDto> teachingClassList,
                                                                    Integer startPos,
                                                                    List<ArrangeTeachingClassRuleDto> courseFixList) {
        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            //用于存放排课单元数据
            LinkedList<TeachingClassUnit> teachingclassUnitList = new LinkedList<>();
            int teachingClassUnitIndex = startPos;
            for (ArrangeTeachingClassDto teachingClass : teachingClassList) {
                //获取教学班的某个授课类型的周学时数量
                Integer weekNum = teachingClass.getWeekNum();
                //连上节次信息
                Integer connectSection = teachingClass.getConnectSection();
                //连上次数
                Integer connectNumber = teachingClass.getConnectNumber();

                String prohibitTimeslotCodes = teachingClass.getProhibitTimeslotCodes();
                List<ArrangeTeachingClassRuleDto> currentFixList = courseFixList.stream()
                        .filter(o -> o.getTeachingClassId().equals(teachingClass.getTeachingClassId())
                                && Objects.equals(o.getHourType(), teachingClass.getHourType()))
                        .sorted(Comparator.comparing(ArrangeTeachingClassRuleDto::getTimeCode))
                        .collect(Collectors.toList());
                if (StrUtil.isNotEmpty(prohibitTimeslotCodes)){
                    currentFixList = currentFixList.stream()
                            .filter(o -> !prohibitTimeslotCodes.contains(o.getTimeCode()))
                            .collect(Collectors.toList());
                }

                if (connectNumber == 0) {
                    //连上次数为0，默认就按照连上节次是1节，去拆分生成教学班排课单元
                    teachingClassUnitIndex = connectNumberIsZero(teachingClass, weekNum,
                            taskId, teachingClassUnitIndex, teachingclassUnitList,currentFixList);
                } else {
                    //过滤掉脏数据，有些教学班没有设置周学时的话，直接跳过
                    if (weekNum != null) {
                        if (weekNum <= connectSection * connectNumber) {
                            teachingClassUnitIndex = weekNumEqualOrLessThan(teachingClass, weekNum, connectSection,
                                    taskId, teachingClassUnitIndex, teachingclassUnitList,currentFixList);
                        } else {
                            teachingClassUnitIndex = weekNumMoreThan(teachingClass, weekNum, connectSection,
                                    connectNumber, taskId, teachingClassUnitIndex, teachingclassUnitList,currentFixList);
                        }
                    }
                }
            }

            return teachingclassUnitList;
        }
        log.info("GenerateSchedulingData--convertToTeachingClassUnit: 没有需要转换成教学班单元的教学班信息~！！");
        //不需要排课，返回空
        return null;
    }

    /**
     * 如果周学时，小于等于连上节次*连上次数
     *
     * @param teachingClass          教学班对象
     * @param weekNum                周学时
     * @param connectSection         连上节次
     * @param taskId                 计划id
     * @param teachingClassUnitIndex 生成的教学班排课单元id
     * @param teachingclassUnitList  用来存储的教学班排课单元列表信息
     * @return
     */
    private int weekNumEqualOrLessThan(ArrangeTeachingClassDto teachingClass,
                                       Integer weekNum,
                                       Integer connectSection,
                                       Integer taskId,
                                       int teachingClassUnitIndex,
                                       LinkedList<TeachingClassUnit> teachingclassUnitList,
                                       List<ArrangeTeachingClassRuleDto> courseFixList) {
        //排除课程里面重复的
        List<String> fixTimeslotCodes = teachingClass.getFixTimeslotCodes();
        if (CollUtil.isNotEmpty(fixTimeslotCodes)) {
            List<String> course = courseFixList.stream().map(ArrangeTeachingClassRuleDto::getTimeCode).collect(Collectors.toList());
            fixTimeslotCodes = fixTimeslotCodes.stream().filter(o -> !course.contains(o)).collect(Collectors.toList());
            teachingClass.setFixTimeslotCodes(fixTimeslotCodes);
        }

        List<Integer> fixTime =  new ArrayList<>();
        if (CollUtil.isNotEmpty(teachingClass.getFixTimeslotCodes())){
            fixTime = teachingClass.getFixTimeslotCodes()
                    .stream().map(Integer::parseInt).sorted().collect(Collectors.toList());
        }

        List<String> codeTimes = new ArrayList<>();

        //计算每周都需要安排的课程的次数；
        //比如，周课时是3，连上2节，那么每周安排一节（2小节），另外一节，每两周上一次
        int weekArrangeNum = weekNum / connectSection;
        //按照每周的排课数量，生成排课教学班单元，按照连上节次来进行安排
        for (int i = 0; i < weekArrangeNum; i++) {
            List<Integer> timeCode = null;
            //从课程那边拿
            if (CollUtil.isNotEmpty(courseFixList) ){
                Integer fix = Integer.valueOf(courseFixList.get(0).getTimeCode());
                timeCode = Collections.singletonList(fix);
                courseFixList.remove(0);
                for (int j = 1; j < connectSection; j++) {
                    Integer finalFix = fix + j;
                    courseFixList = courseFixList.stream()
                            .filter(o -> !o.getTimeCode().equals("0" + String.valueOf(finalFix)))
                            .collect(Collectors.toList());
                }
            }
            if (CollUtil.isEmpty(timeCode)){
                timeCode = findConsecutive(fixTime, connectSection);
            }


            //计算教学班排课单元的id
            teachingClassUnitIndex++;
            TeachingClassUnit teachingClassUnit = generateTeachingClassUnit(teachingClass,
                    teachingClassUnitIndex,
                    taskId,
                    teachingClass.getWeek());

            //设置固排
            if (CollUtil.isNotEmpty(timeCode)) {
                codeTimes = timeCode.stream().map(o -> "0" + o).collect(Collectors.toList());
                teachingClassUnit.setFixTimeslotCodes(codeTimes);
            }else {
                teachingClassUnit.setFixTimeslotCodes(new ArrayList<>());
            }

            teachingclassUnitList.add(teachingClassUnit);
        }
        //每connectSection周，安排otherWeekArrangeNum次课
        //即如果周学时是6，连上节次是4，那么每4周，需要安排2次4节连上的课程；
        int otherWeekArrangeNum = weekNum % connectSection;
        //以连上节次作为周期，如果间隔周次上课的次数大于0
        //那么需要安排每隔连上周数，上otherWeekArrangeNum次课
        if (otherWeekArrangeNum > 0) {
            teachingClassUnitIndex++;
            String weeks = BinaryUtil.swapOneToZero(teachingClass.getWeek(), connectSection, otherWeekArrangeNum);
            TeachingClassUnit teachingClassUnit = generateTeachingClassUnit(teachingClass,
                    teachingClassUnitIndex,
                    taskId,
                    weeks);

            //没有固排可以安排
//            teachingClassUnit.setFixTimeslotCodes(codeTimes);
            teachingClassUnit.setFixTimeslotCodes(new ArrayList<>());

            teachingclassUnitList.add(teachingClassUnit);
        }

        return teachingClassUnitIndex;
    }

    private List<Integer> findConsecutive(List<Integer> list, int numConsecutive) {
        if (CollUtil.isEmpty(list) || list.size() - numConsecutive < 0) {
            return null;
        }
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < list.size() - (numConsecutive - 1); i++) {

            boolean isConsecutive = true;
            for (int j = 0; j < numConsecutive - 1; j++) {
                if (list.get(i + j) + 1 != list.get(i + j + 1)) {
                    isConsecutive = false;
                    break;
                }
            }

            if (isConsecutive) {
                for (int k = i; k < i + numConsecutive; k++) {
                    res.add(list.get(i));
                    list.remove(i);
                }
                return res;
            }
        }
        return null;
    }

    /**
     * 如果周学时，大于连上节次*连上次数，剩余的节数，都按照1节课连上进行处理
     *
     * @param teachingClass          教学班对象
     * @param weekNum                周学时
     * @param connectSection         连上节次
     * @param connectNumber          连上次数
     * @param taskId                 计划id
     * @param teachingClassUnitIndex 生成的教学班排课单元id
     * @param teachingclassUnitList  用来存储的教学班排课单元列表信息
     * @return
     */
    private int weekNumMoreThan(ArrangeTeachingClassDto teachingClass,
                                Integer weekNum,
                                Integer connectSection,
                                Integer connectNumber,
                                Integer taskId,
                                int teachingClassUnitIndex,
                                LinkedList<TeachingClassUnit> teachingclassUnitList,
                                List<ArrangeTeachingClassRuleDto> courseFixList) {
        //排除课程里面重复的
        List<String> fixTimeslotCodes = teachingClass.getFixTimeslotCodes();
        if (CollUtil.isNotEmpty(fixTimeslotCodes)) {
            List<String> course = courseFixList.stream().map(ArrangeTeachingClassRuleDto::getTimeCode).collect(Collectors.toList());
            fixTimeslotCodes = fixTimeslotCodes.stream().filter(o -> !course.contains(o)).collect(Collectors.toList());
            teachingClass.setFixTimeslotCodes(fixTimeslotCodes);
        }

        List<Integer> fixTime = new ArrayList<>();
        if (CollUtil.isNotEmpty(teachingClass.getFixTimeslotCodes())){
                fixTime = teachingClass.getFixTimeslotCodes()
                        .stream().map(Integer::parseInt).sorted().collect(Collectors.toList());
            }


        //周课时减去连上节次乘以连上次数，
        //得到的就是连上节次是1节的排课单元的数量
        int leaveNum = weekNum - connectSection * connectNumber;
        //按照每周的连上次数，生成排课教学班单元，按照连上节次来进行安排
        for (int i = 0; i < connectNumber; i++) {
            List<Integer> timeCode = null;
            //从课程那边拿
            if (CollUtil.isNotEmpty(courseFixList)){
                Integer fix = Integer.valueOf(courseFixList.get(0).getTimeCode());
                timeCode = Collections.singletonList(fix);
                courseFixList.remove(0);
                for (int j = 1; j < connectSection; j++) {
                    Integer finalFix = fix + j;
                    courseFixList = courseFixList.stream()
                            .filter(o -> !o.getTimeCode().equals("0" + String.valueOf(finalFix)))
                            .collect(Collectors.toList());
                }

            }
            if (CollUtil.isEmpty(timeCode)){
                timeCode = findConsecutive(fixTime, connectSection);
            }



            //计算教学班排课单元的id
            teachingClassUnitIndex++;
            //按照连上节次，生成教学班排课单元，将教学班排课单元加入列表
            TeachingClassUnit teachingClassUnit = generateTeachingClassUnit(teachingClass,
                    teachingClassUnitIndex,
                    taskId,
                    teachingClass.getWeek());

            //设置固排
            if (CollUtil.isNotEmpty(timeCode)) {
                teachingClassUnit.setFixTimeslotCodes(timeCode.stream().map(o -> {
                    String s = String.valueOf(o);
                    return "0"+s;
                }).collect(Collectors.toList()));
            }else {
                teachingClassUnit.setFixTimeslotCodes(new ArrayList<>());
            }

            teachingclassUnitList.add(teachingClassUnit);
        }

        //获取固排的课时
        int size = 0;
        if (CollUtil.isNotEmpty(fixTime)) {
            size = fixTime.size();
        }
        //剩余的上课节次，按照1节连上，生成排课教学班单元，来进行安排
        for (int i = 0; i < leaveNum; i++) {


            //计算教学班排课单元的id
            teachingClassUnitIndex++;
            //按照1节课连上，生成教学班排课单元
            TeachingClassUnit teachingClassUnit = generateTeachingClassUnit(teachingClass,
                    teachingClassUnitIndex,
                    taskId,
                    teachingClass.getWeek());
            //将1节连上的教学班排课单元的连上节次设为1
            teachingClassUnit.setConnectSection(1);
            //将1节连上的教学班排课单元的连上次数，设为剩余的上课节次
            teachingClassUnit.setConnectNumber(leaveNum);

            //设置固排课时
            String fixTimeCode = null;
            if (CollUtil.isNotEmpty(courseFixList)){
                fixTimeCode = courseFixList.get(0).getTimeCode();
                courseFixList.remove(0);
            }

            if (StrUtil.isEmpty(fixTimeCode)){
                if (CollUtil.isNotEmpty(fixTime)) {
                    size = fixTime.size();
                    fixTimeCode = "0"+ fixTime.get(0);
                    fixTime.remove(0);
                }
            }

            if (StrUtil.isNotEmpty(fixTimeCode)){
                teachingClassUnit.setFixTimeslotCodes(Collections.singletonList(fixTimeCode));
            }else {
                teachingClassUnit.setFixTimeslotCodes(new ArrayList<>());
            }

            //将教学班排课单元加入列表
            teachingclassUnitList.add(teachingClassUnit);
        }

        return teachingClassUnitIndex;
    }

    /**
     * 生成排课单元信息
     *
     * @param teachingClass 教学班信息
     * @param index         教学班排课单元id
     * @param taskId        学期排课计划id
     * @param weeks         周次信息，二进制字符串
     * @return
     */
    private TeachingClassUnit generateTeachingClassUnit(ArrangeTeachingClassDto teachingClass,
                                                        Integer index,
                                                        Integer taskId,
                                                        String weeks) {
        TeachingClassUnit teachingClassUnit = new TeachingClassUnit();
        //设置排课单元id
        teachingClassUnit.setTeachingClassUnitId(index);
        //设置教学班id
        teachingClassUnit.setTeachingClassId(teachingClass.getTeachingClassId());
        //设置教学班id
        teachingClassUnit.setTeachingClassName(teachingClass.getTeachingClassName());
        //设置教学班类型0:无需选课 1:在线选课 2:分级教学 3:预选教学班
        teachingClassUnit.setTeachingClassType(teachingClass.getTeachingClassType());
        //设置教学班人数
        teachingClassUnit.setTeachingClassSize(teachingClass.getStudentNumber());
        //设置课程任课教室
        teachingClassUnit.setTeacherIds(teachingClass.getTeacherIds());
        //设置课程上课学生id
        teachingClassUnit.setStudentIds(teachingClass.getStudentIds());
        //设置周次
        teachingClassUnit.setClassWeeks(weeks);
        //设置教学班所需教室类型
        teachingClassUnit.setRoomType(teachingClass.getRoomType());
        //设置课程类型，环节/课程
        teachingClassUnit.setCourseType(teachingClass.getFlag());
        //设置授课类型，讲授/实验/上机/其他
        teachingClassUnit.setTeachingType(teachingClass.getHourType());
        //设置排课选课计划id
        teachingClassUnit.setTaskId(taskId);
        //设置禁排的课时信息，多个以逗号分隔
        teachingClassUnit.setProhibitTimeslotCodes(teachingClass.getProhibitTimeslotCodes());
        //设置课程id
        teachingClassUnit.setCourseId(teachingClass.getCourseId());
        //设置课程名称
        teachingClassUnit.setCourseName(teachingClass.getCourseName());
        //设置校区id
        teachingClassUnit.setCampusId(teachingClass.getCampusId());
        //设置连上节次
        teachingClassUnit.setConnectSection(teachingClass.getConnectSection());
        //设置连上次数
        teachingClassUnit.setConnectNumber(teachingClass.getConnectNumber());
        //连上分组
        teachingClassUnit.setTimeGroup(UUID.randomUUID().toString());
        //设置尽量排的课时编码信息，多个以逗号分隔
        teachingClassUnit.setFixTimeslotCodes(teachingClass.getFixTimeslotCodes());
        //设置教学班指定需要分配的教室
        teachingClassUnit.setRoomId(teachingClass.getRoomId());
        //设置行政班id
        teachingClassUnit.setPhyClassId(teachingClass.getClassId());
        //分班标识 UUID生成 相同分组的教学班，标识相同，排课时需要分配相同课时的教学班
        teachingClassUnit.setUniqueShiftSign(teachingClass.getUniqueShiftSign());
        //拆班学生分配 1单数 2双数
        teachingClassUnit.setIsSingle(teachingClass.getIsSingle());
        //课程+教师id字符串，用于拆班课程的区分
        //由于有些课程，需要两个教师教，通过这种方式，来区分不同的课程对应的教学班
        teachingClassUnit.setCourseTeacherIDs(teachingClass.getCourseId() + teachingClass.getTeacherIds());
//        teachingClassUnit.setCourseTeacherIDs(teachingClass.getCourseId() + "");

        return teachingClassUnit;
    }

    /**
     * 判断是否这个教师id，在教师id字符串中，
     *
     * @param teacherIds 教师id字符串，多个以逗号分隔
     * @param teacherId  教师id
     * @return
     */
    protected boolean isTeacherIdExist(String teacherIds, String teacherId) {
        //如果teacherIds为空或者空字符串
        if (StrUtil.isBlank(teacherIds)) {
            //返回不包含
            return false;
        }
        //将字符串进行拆分
        String[] teacherIdArr = teacherIds.split(",");
        for (String splitTeacherId : teacherIdArr) {
            if (splitTeacherId.equals(teacherId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 初始化算法排课的，不同教室类型上课的教学班信息
     *
     * @param taskId                   排课计划id
     * @param teachingClassList        教学班列表
     * @param startPos                 教学班排课单元生成的起始位置；
     * @param fixTeachingClassUnitList 尽量排课剩下的，未分配的教学班排课单元
     * @return
     */
    protected Map<Integer, LinkedList<TeachingClassUnit>> getTeachingClassUnitMap(Integer taskId,
                                                                                  List<ArrangeTeachingClassDto> teachingClassList,
                                                                                  Integer startPos,
                                                                                  LinkedList<TeachingClassUnit> fixTeachingClassUnitList,
                                                                                  List<ArrangeTeachingClassRuleDto> courseFixList) {
        //定义保存转换后的教学班排课单元信息列表
        LinkedList<TeachingClassUnit> retList = new LinkedList<>();
        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            retList.addAll(convertToTeachingClassUnit(taskId, teachingClassList, startPos,courseFixList));
            log.info("GenerateSchedulingData--getTeachingClassUnitMap: 教学班转换为教学班排课单元共{}个", retList.size());
        }

        //将尽量排剩下的未分配的教学班排课单元，加入到自动排课的列表中
        if (fixTeachingClassUnitList != null && !fixTeachingClassUnitList.isEmpty()) {
            log.info("GenerateSchedulingData--getTeachingClassUnitMap: 优先排未处理的教学班排课单元共{}个",
                    (fixTeachingClassUnitList != null ? fixTeachingClassUnitList.size() : 0));
            retList.addAll(fixTeachingClassUnitList);
        }

        if (!retList.isEmpty()) {
            //按教室类型，将排课数据进行分组
            Map<Integer, LinkedList<TeachingClassUnit>> teachingClassUnitMap = retList
                    .stream()
                    .collect(Collectors.groupingBy(TeachingClassUnit::getRoomType, Collectors.toCollection(LinkedList::new)));

            return teachingClassUnitMap;
        }

        log.info("GenerateSchedulingData--getTeachingClassUnitMap: 没有需要转换成课程单元Map的教学班信息~！！");
        return null;
    }

    /**
     * 初始化算法排课的，不同教室类型上课的教学班信息
     *
     * @param timeslotRoomList
     * @return
     */
    protected Map<Integer, LinkedList<TimeslotRoom>> getTimeslotRoomMap(LinkedList<TimeslotRoom> timeslotRoomList) {

        if (timeslotRoomList != null && !timeslotRoomList.isEmpty()) {
            //按教室类型，将教室课时分组列表数据，进行分组
            Map<Integer, LinkedList<TimeslotRoom>> timeslotRoomMap = timeslotRoomList
                    .stream()
                    .collect(Collectors.groupingBy(TimeslotRoom::getRoomType, Collectors.toCollection(LinkedList::new)));
            return timeslotRoomMap;
        }
        log.info("GenerateSchedulingData--getTimeslotRoomMap: 没有需要转换成教室课时分组Map的分组列表信息~！！");
        return null;
    }

    /**
     * 从source列表中，将needToRemove列表中包含的元素，删除
     *
     * @param source       需要处理的源头列表
     * @param needToRemove 需要从源头列表中，清理掉的列表
     * @return
     */
    protected LinkedList<TimeslotRoom> removeTimeslotRoomList(LinkedList<TimeslotRoom> source,
                                                              LinkedList<TimeslotRoom> needToRemove) {
        if (source != null && !source.isEmpty()
                && needToRemove != null && !needToRemove.isEmpty()) {
            //遍历确定分配的教室课时分组信息列表
            for (TimeslotRoom timeslotRoom : needToRemove) {
                //如果是周次信息完全匹配
                if (timeslotRoom.getIsRemove()) {
                    //从原始数据中，删掉已分配的教室课时分组信息
                    source.remove(timeslotRoom);
                }
            }
        }

        return source;
    }
}
